import json
from decimal import Decimal

from django import http
from django.core.paginator import Paginator
from django.db import transaction
from django.http import JsonResponse, HttpResponseForbidden
from django.shortcuts import render

# Create your views here.
from django.utils import timezone
from django.views import View
from django_redis import get_redis_connection

from goods.models import SKU
from meiduo.utils.mixn import AuthenticateView
from meiduo.utils.response_code import RETCODE
from orders.models import OrderGoods, OrderInfo
from users.models import Address
const = 3

class Comment(AuthenticateView):
    def get(self,request):

        """
        sku.url"><img
        ef="sku.url">
        ="price">￥[[

        :param request:
        :return:
        """
        order_id =request.GET.get("order_id")
        order_goods = OrderGoods.objects.get(order_id=order_id)
        skus={
        }
        return render(request,'goods_judge.html')

class OrderSettlementView(AuthenticateView):
    def get(self,request):
        user = request.user
        # 查询当前登录用户的所有收货地址
        addresses = Address.objects.filter(user=user, is_deleted=False)

        # addresses = addresses if addresses.exists() else None
        # 创建redis连接
        redis_conn = get_redis_connection('CARTS')
        # 获取hash购物车数据  {sku_id_1: 1, sku_id_2: 1}
        redis_carts = redis_conn.hgetall('cart_%s' % user.id)
        # 获取set购物车数据 {sku_id_1}
        selected_ids = redis_conn.smembers('select_%s' % user.id)
        # 定义一个字典变量用来包装勾选商品的id和count {sku_id_1: 1}
        cart_dict = {}
        for sku_id_bytes in selected_ids:
            cart_dict[int(sku_id_bytes)] = int(redis_carts[sku_id_bytes])

        # 查询所有要购买商品的sku模型
        skus = SKU.objects.filter(id__in=cart_dict.keys())

        total_count = 0  # 记录商品总数量
        total_amount = Decimal('0.00')  # 商品总价

        # 遍历查询集,给每个sku模型多定义两个属性
        for sku in skus:
            sku.count = cart_dict[sku.id]
            sku.amount = sku.price * sku.count
            total_count += sku.count
            total_amount += sku.amount

        freight = Decimal('10.00')  # 运费

        context = {
            'addresses': addresses,
            'skus': skus,
            'total_count': total_count,
            'total_amount': total_amount,
            'freight': freight,
            'payment_amount': total_amount + freight
        }
        return render(request, 'place_order.html', context)

class OrderCommitView(AuthenticateView):
    """提交订单"""

    def post(self, request):

        # 接收前端传入的收货地址,及支付方式
        json_dict = json.loads(request.body.decode())
        address_id = json_dict.get('address_id')
        pay_method = int(json_dict.get('pay_method'))
        # 校验
        if all([address_id, pay_method]) is False:
            return http.HttpResponseForbidden('缺少必传参数')

        try:
            address = Address.objects.get(id=address_id)
        except Address.DoesNotExist:
            return http.HttpResponseForbidden('收货有误')

        if pay_method not in [OrderInfo.PAY_METHODS_ENUM.get('CASH'), OrderInfo.PAY_METHODS_ENUM.get('ALIPAY')]:
            return http.HttpResponseForbidden('支付方式有误')

        # 20190511121110 + %09d % user.id
        user = request.user
        # 生成订单编号
        # order_id = timezone.localtime().strftime('%Y%m%d%H%M%S') + ('%09d' % user.id)
        order_id = timezone.now().strftime('%Y%m%d%H%M%S') + ('%09d' % user.id)

        # 订单状态
        status = (OrderInfo.ORDER_STATUS_ENUM.get('UNPAID')
                  if pay_method == OrderInfo.PAY_METHODS_ENUM.get('ALIPAY')
                  else OrderInfo.ORDER_STATUS_ENUM.get('UNSEND'))

        with transaction.atomic():  # 手动创建事务

            # 创建事务保存点
            save_point = transaction.savepoint()
            try:
                # 创建一个订单基本信息模型 并存储
                order = OrderInfo.objects.create(
                    order_id=order_id,
                    user=user,
                    address=address,
                    total_count=0,
                    total_amount=Decimal('0.00'),
                    freight=Decimal('10.00'),
                    pay_method=pay_method,
                    status=status
                )

                # 创建redis连接
                redis_conn = get_redis_connection('CARTS')
                # 获取hash数据
                redis_cart = redis_conn.hgetall('cart_%s' % user.id)
                # 获取set集合数据
                cart_selected = redis_conn.smembers('select_%s' % user.id)
                cart_dict = {}
                # 遍历set把要购买的sku_id和count包装到一个新字典中
                for sku_id_bytes in cart_selected:
                    cart_dict[int(sku_id_bytes)] = int(redis_cart[sku_id_bytes])

                # 遍历用来包装所有要购买商品的字典
                for sku_id in cart_dict:
                    while True:
                        # 通过sku_id获取到sku模型
                        sku = SKU.objects.get(id=sku_id)
                        # 获取当前商品要购买的数量
                        buy_count = cart_dict[sku_id]
                        # 获取当前商品的库存和销量
                        origin_stock = sku.stock
                        origin_sales = sku.sales

                        # import time
                        # time.sleep(5)

                        # 判断库存
                        if buy_count > origin_stock:
                            # 回滚
                            transaction.savepoint_rollback(save_point)
                            return http.JsonResponse({'code': RETCODE.STOCKERR, 'errmsg': '库存不足'})

                        new_stock = origin_stock - buy_count  # 计算新的库存
                        new_sales = origin_sales + buy_count  # 计算新的销量
                        # 修改sku的库存
                        # sku.stock = new_stock
                        # # 修改sku的销量
                        # sku.sales = new_sales
                        # sku.save()
                        # 使用乐观锁解决抢夺时数据库写入脏数据
                        result = SKU.objects.filter(id=sku_id, stock=origin_stock).update(stock=new_stock,
                                                                                          sales=new_sales)
                        if result == 0:  # 如果下单失败,给它无限次下单机会,只到成功,或库存不足
                            continue

                        # 修改spu的销量
                        sku.spu.sales += buy_count
                        sku.spu.save()

                        # 存储订单商品记录
                        OrderGoods.objects.create(
                            order=order,
                            sku=sku,
                            count=buy_count,
                            price=sku.price
                        )

                        order.total_count += buy_count  # 累加订单商品总数量
                        order.total_amount += (sku.price * buy_count)  # 累加商品总价

                        break  # 如果当前这个商品下单成功跳出死循环

                order.total_amount += order.freight  # 累加运费
                order.save()
            except Exception:
                transaction.savepoint_rollback(save_point)  # 回滚
                return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '下单失败'})
            else:
                transaction.savepoint_commit(save_point)  # 提交事务

        pl = redis_conn.pipeline()
        pl.hdel('carts_%s' % user.id, *cart_selected)  # 删除hash中已经购买商品数据{2: 1}
        pl.delete('select_%s' % user.id)
        pl.execute()

        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '提交订单成功', 'order_id': order_id})

class OrderManagementView(AuthenticateView):
    """订单显示视图"""

    def get(self, request, page):
        user = request.user
        orders = OrderInfo.objects.filter(user=user).order_by("-update_time")
        if not orders:
            return render(request, "user_center_order.html")
        paginator = Paginator(orders, const)
        # 创建分页
        total_page = paginator.num_pages
        try:
            page_orders = paginator.page(page)
        except:
            return HttpResponseForbidden("参数错误")
        # page_orders时一个列表
        for order in page_orders:
            # 遍历该用户所有历史订单
            order.sku_list = []
            order.pay_method_name = order.PAY_METHOD_CHOICES[order.pay_method - 1][1]
            order.status_name = order.ORDER_STATUS_CHOICES[order.status - 1][1]
            order_good_qs = OrderGoods.objects.filter(order=order)
            for order_good in order_good_qs:
                # 遍历当前订单下所有sku
                sku = order_good.sku
                sku.count = order_good.count
                sku.amount = sku.price * sku.count

                order.sku_list.append(sku)
        context = {
            "page_orders": page_orders,
            "total_page": total_page,
            "page_num": page,
        }
        return render(request, "user_center_order.html", context)

class ReviewView(AuthenticateView):
    """商品评价视图"""

    def get(self, request):

        order_id = request.GET.get("order_id")
        # 校验数据
        try:
            order = OrderInfo.objects.get(order_id=order_id, user=request.user,
                                          status=OrderInfo.ORDER_STATUS_ENUM["UNCOMMENT"])
        except OrderInfo.DoesNotExist:
            return HttpResponseForbidden("参数有误")

        order_goods = order.skus.all()
        skus = []
        for order_good in order_goods:
            # 格式转换
            sku = order_good.sku
            skus.append({
                "order_id": order_id,
                "sku_id": sku.id,
                "default_image_url": sku.default_image.url,
                "name": sku.name,
                "price": str(sku.price),
                "score": order_good.score,
                "comment": order_good.comment
            })
        context = {
            "uncomment_goods_list": skus
        }
        return render(request, "goods_judge.html", context)

    def post(self, request):
        # 获取数据
        data_dict = json.loads(request.body.decode())
        order_id = data_dict.get("order_id")
        sku_id = data_dict.get("sku_id")
        comment = data_dict.get("comment")
        score = data_dict.get("score")
        is_anonymous = data_dict.get("is_anonymous")  # bool类型
        # 校验数据
        if not all([order_id, sku_id, comment, score]):
            return HttpResponseForbidden("传入参数有误")
        user = request.user
        try:
            order = OrderInfo.objects.get(order_id=order_id, user=user)
        except OrderInfo.DoesNotExist:
            return HttpResponseForbidden("传入参数有误")

        if order.status == order.ORDER_STATUS_ENUM["FINISHED"]:
            # 已评价提前响应
            return JsonResponse({"code": RETCODE.OK, "errmsg": "ok"})
        elif order.status == order.ORDER_STATUS_ENUM["UNCOMMENT"]:
            try:
                order_good = OrderGoods.objects.get(order_id=order_id, is_commented=False, sku_id=sku_id)
            except OrderGoods.DoesNotExist:
                return HttpResponseForbidden("传入参数有误")
            if len(comment) <= 5:
                return HttpResponseForbidden("传入参数有误")
            if score not in range(1, 6):
                return HttpResponseForbidden("传入参数有误")
            if not isinstance(is_anonymous, bool):
                return HttpResponseForbidden("传入参数有误")

            # 业务逻辑
            order_good.comment = comment
            order_good.is_commented = True
            order_good.is_anonymous = is_anonymous
            order_good.score = score

            order.status = order.ORDER_STATUS_ENUM["FINISHED"]

            order_good.save()
            order.save()

            # 响应
            return JsonResponse({"code": RETCODE.OK, "errmsg": "ok"})
        else:
            return HttpResponseForbidden("参数有误")
class OrderSuccessView(AuthenticateView):


    def get(self, request):
        """展示订单提交成功界面"""
        query_dict = request.GET
        payment_amount = query_dict.get('payment_amount')
        order_id = query_dict.get('order_id')
        pay_method = query_dict.get('pay_method')
        # 校验
        try:
            OrderInfo.objects.get(order_id=order_id, pay_method=pay_method, total_amount=payment_amount)

        except OrderInfo.DoesNotExist:
            return http.HttpResponseForbidden('订单有误')

        context = {
            'payment_amount': payment_amount,
            'order_id': order_id,
            'pay_method': pay_method
        }
        return render(request, 'order_success.html', context)


class Comment(AuthenticateView):
    def get(self,request):
        """ 获取新增评论界面"""
        order_id = request.GET.get("order_id")
        order_goods = OrderGoods.objects.filter(order_id=order_id,is_commented=False)
        uncomment_goods_list=[]
        for i in order_goods:
            sku = i.sku
            suk_img = sku.default_image.url
            skus={'default_image_url':suk_img,
             'name':sku.name,
                 "price":str(sku.price),
                'sku_id':str(i.sku_id),
                  'order_id':order_id
            }
            uncomment_goods_list.append(skus)


        container={'uncomment_goods_list':uncomment_goods_list}
        return render(request,'goods_judge.html',container)

    def post(self,request):
        """ 新增评论"""
        query_bytes =request.body.decode()
        query_dict = json.loads(query_bytes)
        order_id=query_dict.get('order_id')
        sku_id=query_dict.get('sku_id')
        comment=query_dict.get('comment')
        score=query_dict.get('score')
        is_anonymous=bool(query_dict.get('is_anonymous'))
        if all([order_id,sku_id,comment,score]) is False:
            return http.HttpResponseForbidden("不好意思数据不齐全,非法请求")

        order_good = OrderGoods.objects.get(order_id=order_id,sku_id=sku_id)
        order_good.comment=comment
        order_good.score=score
        order_good.is_anonymous=is_anonymous
        order_good.is_commented=True
        order_good.save()
        order = order_good.order
        order_goods = OrderGoods.objects.filter(order_id=order_id,is_commented=False).count()
        if order_goods==0:
            order.status=5
            order.save()
            return http.JsonResponse({"code": "1", "errmsg": "评论完成"})
        return http.JsonResponse({"code":"0","errmsg":"评论完成"})

class GetComment(View):
    def get(self,request,sku_id):
        """ 详情页获取评论"""
        comment_list=[]
        comment_data = OrderGoods.objects.filter(sku_id=sku_id)
        for i in comment_data:
            order_id = i.order_id
            user_order = OrderInfo.objects.get(order_id=order_id).user
            if i.is_anonymous:
                a = user_order.username
                b=len(a)-2
                username='%s'%a[0]+b*'*'+a[-1]
            else:
                username=user_order.username
            comment ={'comment':i.comment,
            'score':i.score,
             'name':username}
            comment_list.append(comment)
        return http.JsonResponse({'code':RETCODE.OK,'errmsg':"ok",'comment_list':comment_list})
